/******************************************************************************* * Copyright (c) 2005, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal.commands; import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.common.EventManager; import org.eclipse.jface.resource.ImageDescriptor; /** * <p> * A central lookup facility for images for commands. Images can be associated * with commands using this manager. * </p> * <p> * Clients may instantiate, but must not extend. * </p> * <p> * <strong>PROVISIONAL</strong>. This class or interface has been added as part * of a work in progress. There is a guarantee neither that this API will work * nor that it will remain the same. Please do not use this API without * consulting with the Platform/UI team. * </p> * <p> * This class is eventually intended to exist in * <code>org.eclipse.jface.commands</code>. * </p> * */ public final class CommandImageManager extends EventManager { /** * The type of image to display in the default case. */ public static final int TYPE_DEFAULT = 0; /** * The type of image to display if the corresponding command is disabled. */ public static final int TYPE_DISABLED = 1; /** * The type of image to display if the mouse is hovering over the command * and the command is enabled. */ public static final int TYPE_HOVER = 2; /** * The map of command identifiers (<code>String</code>) to images. The * images are an array indexed by type. The values in the array are either * an <code>ImageDescriptor</code> or a <code>Map</code> of style (<code>String</code>) * to <code>ImageDescriptor</code>. */ private final Map imagesById = new HashMap(); /** * Adds a listener to this command image manager. The listener will be * notified when the set of image bindings changes. This can be used to * track the global appearance and disappearance of image bindings. * * @param listener * The listener to attach; must not be <code>null</code>. */ public final void addCommandImageManagerListener( final ICommandImageManagerListener listener) { addListenerObject(listener); } /** * Binds a particular image path to a command id, type and style triple * * @param commandId * The identifier of the command to which the image should be * bound; must not be <code>null</code>. * @param type * The type of image to retrieve. This value must be one of the * <code>TYPE</code> constants defined in this class. * @param style * The style of the image; may be <code>null</code>. * @param url * The URL to the image. Should not be <code>null</code>. */ public final void bind(final String commandId, final int type, final String style, final URL url) { final ImageDescriptor descriptor = ImageDescriptor.createFromURL(url); bind(commandId, type, style, descriptor); } /** * Binds a particular image path to a command id, type and style triple * * @param commandId * The identifier of the command to which the image should be * bound; must not be <code>null</code>. * @param type * The type of image to retrieve. This value must be one of the * <code>TYPE</code> constants defined in this class. * @param style * The style of the image; may be <code>null</code>. * @param descriptor * The image descriptor. Should not be <code>null</code>. */ public final void bind(final String commandId, final int type, final String style, final ImageDescriptor descriptor) { Object[] images = (Object[]) imagesById.get(commandId); if (images == null) { images = new Object[3]; imagesById.put(commandId, images); } if ((type < 0) || (type >= images.length)) { throw new IllegalArgumentException( "The type must be one of TYPE_DEFAULT, TYPE_DISABLED and TYPE_HOVER."); //$NON-NLS-1$ } final Object typedImage = images[type]; if (style == null) { if ((typedImage == null) || (typedImage instanceof ImageDescriptor)) { images[type] = descriptor; } else if (typedImage instanceof Map) { final Map styleMap = (Map) typedImage; styleMap.put(style, descriptor); } } else { if (typedImage instanceof Map) { final Map styleMap = (Map) typedImage; styleMap.put(style, descriptor); } else if (typedImage instanceof ImageDescriptor || typedImage == null) { final Map styleMap = new HashMap(); styleMap.put(null, typedImage); styleMap.put(style, descriptor); images[type] = styleMap; } } fireManagerChanged(new CommandImageManagerEvent(this, new String[] { commandId }, type, style)); } /** * Removes all of the images from this manager. */ public final void clear() { imagesById.clear(); if (isListenerAttached()) { final String[] commandIds = (String[]) imagesById.keySet().toArray( new String[imagesById.size()]); fireManagerChanged(new CommandImageManagerEvent(this, commandIds, TYPE_DEFAULT, null)); } } /** * Notifies all of the listeners to this manager that the image bindings * have changed. * * @param event * The event to send to all of the listeners; must not be * <code>null</code>. */ private final void fireManagerChanged(final CommandImageManagerEvent event) { if (event == null) { throw new NullPointerException(); } final Object[] listeners = getListeners(); for (int i = 0; i < listeners.length; i++) { final ICommandImageManagerListener listener = (ICommandImageManagerListener) listeners[i]; listener.commandImageManagerChanged(event); } } /** * Generates a style tag that is not currently used for the given command. * This can be used by applications trying to create a unique style for a * new set of images. * * @param commandId * The identifier of the command for which a unique style is * required; must not be <code>null</code>. * @return A style tag that is not currently used; may be <code>null</code>. */ public final String generateUnusedStyle(final String commandId) { final Object[] existingImages = (Object[]) imagesById.get(commandId); if (existingImages == null) { return null; } final Set existingStyles = new HashSet(3); for (int type = 0; type < existingImages.length; type++) { final Object styledImages = existingImages[type]; if (styledImages instanceof ImageDescriptor) { existingStyles.add(null); } else if (styledImages instanceof Map) { final Map styleMap = (Map) styledImages; existingStyles.addAll(styleMap.keySet()); } } if (!existingStyles.contains(null)) { return null; } String generatedStyle = "AUTOGEN:::"; //$NON-NLS-1$ int index = 0; while (existingStyles.contains(generatedStyle)) { generatedStyle += (index++ % 10); } return generatedStyle; } /** * Retrieves the default image associated with the given command in the * default style. * * @param commandId * The identifier to find; must not be <code>null</code>. * @return An image appropriate for the given command; never * <code>null</code>. */ public final ImageDescriptor getImageDescriptor(final String commandId) { return getImageDescriptor(commandId, TYPE_DEFAULT, null); } /** * Retrieves the image of the given type associated with the given command * in the default style. * * @param commandId * The identifier to find; must not be <code>null</code>. * @param type * The type of image to retrieve. This value must be one of the * <code>TYPE</code> constants defined in this class. * @return An image appropriate for the given command; <code>null</code> * if the given image type cannot be found. */ public final ImageDescriptor getImageDescriptor(final String commandId, final int type) { return getImageDescriptor(commandId, type, null); } /** * Retrieves the image of the given type associated with the given command * in the given style. * * @param commandId * The identifier to find; must not be <code>null</code>. * @param type * The type of image to retrieve. This value must be one of the * <code>TYPE</code> constants defined in this class. * @param style * The style of the image to retrieve; may be <code>null</code>. * @return An image appropriate for the given command; <code>null</code> * if the given image style and type cannot be found. */ public final ImageDescriptor getImageDescriptor(final String commandId, final int type, final String style) { if (commandId == null) { throw new NullPointerException(); } final Object[] images = (Object[]) imagesById.get(commandId); if (images == null) { return null; } if ((type < 0) || (type >= images.length)) { throw new IllegalArgumentException( "The type must be one of TYPE_DEFAULT, TYPE_DISABLED and TYPE_HOVER."); //$NON-NLS-1$ } Object typedImage = images[type]; if (typedImage == null) { return null; } if (typedImage instanceof ImageDescriptor) { return (ImageDescriptor) typedImage; } if (typedImage instanceof Map) { final Map styleMap = (Map) typedImage; Object styledImage = styleMap.get(style); if (styledImage instanceof ImageDescriptor) { return (ImageDescriptor) styledImage; } if (style != null) { styledImage = styleMap.get(null); if (styledImage instanceof ImageDescriptor) { return (ImageDescriptor) styledImage; } } } return null; } /** * Retrieves the default image associated with the given command in the * given style. * * @param commandId * The identifier to find; must not be <code>null</code>. * @param style * The style of the image to retrieve; may be <code>null</code>. * @return An image appropriate for the given command; <code>null</code> * if the given image style cannot be found. */ public final ImageDescriptor getImageDescriptor(final String commandId, final String style) { return getImageDescriptor(commandId, TYPE_DEFAULT, style); } /** * Removes a listener from this command image manager. * * @param listener * The listener to be removed; must not be <code>null</code>. */ public final void removeCommandImageManagerListener( final ICommandImageManagerListener listener) { removeListenerObject(listener); } }